package org.pupil.socket.server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.pupil.common.constants.MsgType;
import org.pupil.common.constants.RpcInvoker;
import org.pupil.filter.*;
import org.pupil.invoke.Invocation;
import org.pupil.invoke.Invoker;
import org.pupil.invoke.InvokerFactory;
import org.pupil.socket.codec.MsgHeader;
import org.pupil.socket.codec.RpcProtocol;
import org.pupil.socket.codec.RpcRequest;
import org.pupil.socket.codec.RpcResponse;

import java.util.List;

/**
 * @Description: 服务端请求消息处理器
 * @Author: pupil
 * @Date: 2024/07/09 下午 4:48
 */
public class ServerHandler extends SimpleChannelInboundHandler<RpcProtocol<RpcRequest>> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcProtocol<RpcRequest> rpcProtocol) throws Exception {
        // 获取消息体
        final RpcRequest rpcRequest = rpcProtocol.getBody();
        // 创建响应消息
        final RpcResponse response = new RpcResponse();
        // 创建响应类型的消息
        final RpcProtocol<RpcResponse> resRpcProtocol = new RpcProtocol<>();
        // 获取请求头
        final MsgHeader header = rpcProtocol.getMsgHeader();
        // 修改请求头的消息类型
        header.setMsgType((byte) MsgType.RESPONSE.ordinal());
        // 获取方法调用对象
        final Invoker invoker = InvokerFactory.get(RpcInvoker.JDK);
        try {
            final List<Filter> serverBeforeFilters = FilterFactory.getServerBeforeFilters();
            if (!serverBeforeFilters.isEmpty()){
                final FilterData<RpcRequest> rpcRequestFilterData = new FilterData<>(rpcRequest);
                final FilterLoader filterLoader = new FilterLoader();
                filterLoader.addFilter(serverBeforeFilters);
                final FilterResponse filterResponse = filterLoader.doFilter(rpcRequestFilterData);
                if (!filterResponse.getResult()) {
                    throw filterResponse.getException();
                }
            }
            // 进行方法反射调用，获取方法返回结果
            final Object data = invoker.invoke(new Invocation(rpcRequest));
            response.setData(data);
        }catch (Exception e){
            response.setException(e);
        }finally {
            final List<Filter> serverAfterFilters = FilterFactory.getServerAfterFilters();
            if (!serverAfterFilters.isEmpty()){
                final FilterData<RpcResponse> rpcResponseFilterData = new FilterData<>(response);
                final FilterLoader filterLoader = new FilterLoader();
                filterLoader.addFilter(serverAfterFilters);
                final FilterResponse filterResponse = filterLoader.doFilter(rpcResponseFilterData);
                if (!filterResponse.getResult()) {
                    throw filterResponse.getException();
                }
            }
        }

        // 设置请求头
        resRpcProtocol.setMsgHeader(header);
        // 设置请求体
        resRpcProtocol.setBody(response);
        // 写出数据
        ctx.writeAndFlush(resRpcProtocol);
    }
}
